<script setup lang="ts">
import HandsonTable from 'handsontable'
import { registerAllModules } from 'handsontable/registry'
import 'handsontable/styles/handsontable.css'
import 'handsontable/styles/ht-theme-main.css'
import '@/style/handsontable-theme.css'
import { registerLanguageDictionary, zhCN } from 'handsontable/i18n'
import { HyperFormula } from 'hyperformula'
import useReportDetail, { type LoadReportResponse } from '../useReportDetail'
import { loadHistoryDataOfWaterBalance, saveReportDataOfCompanyWeight, updateReportDataOfCompanyWeight } from '@/api/modules/dataReport'
import useTheme from '../useTheme'
import { REPORT_FORM_ID, REPORT_ID, REPORT_WATER_TYPE } from '@/enum'
import type { SaveParams } from '../type'
import { HEADER_CELL_CLASS, READONLY_CELL_CLASS, ROUND_NUMBER } from '../config'
import useValidate from '../useValidate'

defineOptions({ name: 'CompanyWeight1' })
const props = defineProps<{
  time: string
  socialCreditCode: string
  company: string
  readonly?: boolean
  /** 加载远程数据时使用的ID */
  dataId?: number
}>()

registerLanguageDictionary(zhCN)

// register Handsontable's modules
registerAllModules()

// KEYS
const KEYS = ['m', 'name', 'xmcQsl', 'xmcXmsc', 'xmcShbg', 'xmcSt', 'xmcCn', 'xmcKqnlh', 'xmcStzllh', 'xmcLydw', 'xmcWwdw', 'xmcSgsfyl', 'xmcTsl', 'x', 'xmcRemark']

const HEADERS = [
  [
    '月份',
    '取水名称',
    '取水量',
    '其中洗煤厂用水（吨）',
    null,
    null,
    null,
    null,
    '生态治理绿化',
    '联营单位',
    '外委单位',
    '疏干水富余量',
    '退水量',
    '平衡情况',
    '备注',
  ],
  [
    null,
    null,
    null,
    '洗煤生产',
    '办公生活',
    '食堂',
    '采暖',
    '矿区内绿化',
    null,
    null,
    null,
    null,
    null,
    null,
    null,
  ],
]
const HEADERS_MERGE_CELLS = [
  { row: 0, col: 0, rowspan: 2, colspan: 1 },
  { row: 0, col: 1, rowspan: 2, colspan: 1 },
  { row: 0, col: 2, rowspan: 2, colspan: 1 },
  { row: 0, col: 3, rowspan: 1, colspan: 5 },
  { row: 0, col: 8, rowspan: 2, colspan: 1 },
  { row: 0, col: 9, rowspan: 2, colspan: 1 },
  { row: 0, col: 10, rowspan: 2, colspan: 1 },
  { row: 0, col: 11, rowspan: 2, colspan: 1 },
  { row: 0, col: 12, rowspan: 2, colspan: 1 },
  { row: 0, col: 13, rowspan: 2, colspan: 1 },
  { row: 0, col: 14, rowspan: 2, colspan: 1 },
]
const wrapper = ref<HTMLElement>()
const hot = ref<HandsonTable>()
const loadReportResponse = shallowRef<LoadReportResponse>()

const { getReportDataById, beforeChangeHook } = useReportDetail()
async function loadCurrentData() {
  const m = props.time.split('-')[1]
  const defaults = [
    [
      `${Number(m)}月`,
      '自来水',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '=IF(SUM(D3:M3)=C3+0,"平衡","不平衡")',
      '',
    ],
    [
      null,
      '矿井水',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '=IF(SUM(D4:M4)=C4+0,"平衡","不平衡")',
      null,
    ],
    [
      null,
      '生活污水',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '=IF(SUM(D5:M5)=C5+0,"平衡","不平衡")',
      null,
    ],
    [
      null,
      '黄河水',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '=IF(SUM(D6:M6)=C6+0,"平衡","不平衡")',
      null,
    ],
    [
      null,
      '外购中水',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '',
      '=IF(SUM(D7:M7)=C7+0,"平衡","不平衡")',
      null,
    ],
  ]
  let dataList = defaults
  if (props.dataId) {
    const data = await getReportDataById(props.dataId)
    loadReportResponse.value = data
    if (data.webReportData) {
      try {
        dataList = JSON.parse(data.webReportData) as any[]
      }
      catch (e) {
        console.error(e)
        ElMessage.error('[webReportData]数据解析错误')
        dataList = defaults
      }
    }
    // 忽略远程的配置
  }
  return dataList
}
async function loadHistoryData() {
  const defaults: any = []

  const { data } = await loadHistoryDataOfWaterBalance(
    props.time,
    props.socialCreditCode,
    // 洗煤厂
    REPORT_ID.COMPANY_WEIGHT_2,
  )

  const dataList = defaults
  if (data) {
    for (const s of data) {
      if (s) {
        try {
          const i = data.indexOf(s)
          const start = (i + 1) * 5 + 2
          const ss = JSON.parse(s)
          // 要更新下历史的平衡公式
          for (let j = 0; j < ss.length; j++) {
            const row = start + j + 1
            const item = ss[j]
            // 公式在倒数第二个索引
            item[item.length - 2] = `=IF(SUM(D${row}:M${row})=C${row}+0,"平衡","不平衡")`
          }
          dataList.push(...ss)
        }
        catch (error) {
          console.error(error)
        }
      }
    }
  }
  return dataList
}

function getSummaryDataWithFormula(data: any[][], gx = ['自来水', '矿井水', '生活污水', '黄河水', '外购中水']) {
  const m = data.length
  const n = data[0]?.length ?? 0
  const g = gx.length
  const start = 2
  const loop = Math.floor(m / g)
  const summary = [] as any[]
  const keys = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('')
  for (let i = 0; i < g; i++) {
    const temp = [] as string[]
    for (let j = 0; j < n; j++) {
      let str = ''
      if (j < 2) {
        // 第1、2列不参与公式的生成
        str = j === 0 ? '汇总' : gx[i]
        temp.push(str)
        continue
      }
      if (j >= n - 2) {
        // 最后两列不参与公式的生成（平衡情况，备注）
        str = ''
        temp.push(str)
        continue
      }
      const col = keys[j]
      for (let k = 0; k < loop; k++) {
        str += `+${col}${k * g + i + 1 + start}`
      }
      temp.push(str)
    }
    const row = [
      ...temp.slice(0, 2),
      ...temp.slice(2, -2).map(v => `=ROUND(${v.substring(1)},${ROUND_NUMBER})`),
      ...temp.slice(-2),
    ]
    // console.log(row)
    summary.push(row)
  }
  return summary
}

function getMergeCells(m: number, n: number, g = 5, start = 2) {
  const newMergeCells = [
    ...HEADERS_MERGE_CELLS,
  ]
  for (let i = 0; i < m; i = (Math.floor(i / g) + 1) * g) {
    for (let j = 0; j < n; j++) {
      // 需要操作的合并单元格所在列在第1列
      if (j === 0) {
        newMergeCells.push({
          row: i + start,
          col: j,
          rowspan: g,
          colspan: 1,
        })
      }
    }
  }
  return newMergeCells
}

function updateSettings(m: number, n: number, g = 5, start = 2) {
  // 填报情况下（非只读）第3行到第7行可写
  if (hot.value) {
    hot.value.updateSettings({
      cells: (row: number, col: number) => {
        if (row < HEADERS.length) {
          return { className: `htCenter htMiddle ${HEADER_CELL_CLASS}` }
        }
        // 平衡情况(第I列）要计算出来，只读
        // 这些行的第1、2列也只读
        return !props.readonly && row >= 2 && row <= 6 && col !== 13 && col !== 0 && col !== 1
          ? { readOnly: false, type: col !== 14 ? 'numeric' : 'text' }
          : {}
      },
      mergeCells: getMergeCells(m, n, g, start),
    })
  }
}

async function loadData() {
  const current = await loadCurrentData()
  const history = await loadHistoryData()

  const data = [
    ...current,
    ...history,
  ]
  const summary = getSummaryDataWithFormula(data)
  const ret = [
    ...HEADERS,
    ...data,
    ...summary,
  ]
  hot.value?.loadData(ret)
  return ret
}

async function init() {
  if (!wrapper.value)
    return
  hot.value = new HandsonTable(wrapper.value, {
    fixedRowsTop: HEADERS.length,
    selectionMode: 'single',
    readOnly: true,
    // disableVisualSelection: props.readonly,
    language: zhCN.languageCode,
    data: [
      ...HEADERS,
    ],
    formulas: {
      engine: HyperFormula,
    },
    className: 'htCenter htMiddle',
    readOnlyCellClassName: READONLY_CELL_CLASS,
    stretchH: 'all',
    // autoColumnSize: true,
    colWidths: 100,
    manualColumnResize: true,
    colHeaders: true,
    rowHeaders: true,
    contextMenu: false,
    mergeCells: [
      ...HEADERS_MERGE_CELLS,
    ],
    licenseKey: 'non-commercial-and-evaluation',
  })

  // 处理输入的值，parseFloat
  hot.value.addHook('beforeChange', beforeChangeHook([
    [2, 14],
    [3, 14],
    [4, 14],
    [5, 14],
    [6, 14],
  ]))

  // 选中单元格后可以直接输入
  hot.value.addHook('afterSelectionEnd', (row, col) => {
    if (props.readonly)
      return
    const value = hot.value?.getSourceDataAtCell(row, col)
    hot.value?.getActiveEditor()?.beginEditing()
    hot.value?.getActiveEditor()?.setValue(value)
  })

  // debug
  if (import.meta.env.VITE_REPORT_DEBUG === '1') {
    hot.value.addHook('afterSelection', (row, col) => {
      if (row > -1 && col > -1) {
        console.info(`[${row},${col}] ${hot.value?.getSourceDataAtCell(row, col)}`)
        document.execCommand('copy')
      }
    })
  }
}

async function bootstrap() {
  init()
  const d = await loadData()
  // 表主体数据集合
  const t = d.slice(HEADERS.length)
  updateSettings(t.length, t[0].length)
}

const { isDark } = useTheme(async () => {
  if (hot.value) {
    hot.value.destroy()
    hot.value = undefined
    await nextTick()
    await bootstrap()
  }
})

onMounted(bootstrap)

function getSourceData() {
  return hot.value?.getSourceData() ?? []
}

function getList() {
  // 填报的区域在第3行到第7行
  const d = getSourceData().slice(2, 7)
  // console.log(d[0].length === KEYS.length)
  return d.map((v: any, i) => {
    const ret = KEYS.reduce((acc, vv, ii) => {
      acc[vv] = v[ii]
      return acc
    }, {} as any)
    ret.nameCode = [
      REPORT_WATER_TYPE.A,
      REPORT_WATER_TYPE.B,
      REPORT_WATER_TYPE.C,
      REPORT_WATER_TYPE.D,
      REPORT_WATER_TYPE.E,
    ][i]
    return ret
  })
}

function getSettings() {
  return {
    // 这个表的合并单元格时动态的，所以不存它的配置
    mergeCells: {},
    // 填报的区域在第3行到第7行 只保存填报区域
    sourceData: getSourceData().slice(2, 7),
    list: getList(),
    extraMapData: {},
  }
}

async function save({
  saveType,
  beforeSaveFn,
  afterSaveFn,
}: SaveParams) {
  const s = getSettings()
  const src = loadReportResponse.value
  const params = {
    ...src,
    // 洗煤厂
    reportId: REPORT_ID.COMPANY_WEIGHT_2,
    formId: REPORT_FORM_ID.COMPANY_WEIGHT_2,
    saveType,
    dataList: s.list,
    webReportData: JSON.stringify(getSourceData().slice(2, 7)),
    webReportFormat: JSON.stringify({
      mergeCells: s.mergeCells,
    }),
  }

  if (!hot.value)
    return
  // 校验表格数据类型
  const validate = useValidate(hot.value)
  const result = await validate().catch(() => {})
  hot.value.render()
  if (typeof result !== 'boolean') {
    return
  }

  let before = true
  // 保存前的回调
  if (beforeSaveFn) {
    before = await beforeSaveFn(
      REPORT_ID.COMPANY_WEIGHT_2,
      REPORT_FORM_ID.COMPANY_WEIGHT_2,
      params,
    )
  }
  if (before) {
    let responseId: number | undefined
    let after = true
    try {
      if (params.id) {
        await updateReportDataOfCompanyWeight(params)
      }
      else {
        const { data } = await saveReportDataOfCompanyWeight(params)
        responseId = data.id
      }
    }
    catch (e) {
      after = false
      hot.value.render()
    }
    // 保存后的回调
    after && afterSaveFn?.(
      REPORT_ID.COMPANY_WEIGHT_2,
      REPORT_FORM_ID.COMPANY_WEIGHT_2,
      params,
      responseId,
    )
  }
}

defineExpose({
  getSettings,
  save,
})
</script>

<template>
  <div class="h-full w-full">
    <div
      ref="wrapper" class="h-full w-full overflow-auto" :class="{
        'ht-theme-main-dark': isDark,
        'ht-theme-main': !isDark,
      }"
    />
  </div>
</template>
